package com.hmall.gateway.route;

import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.hmall.common.utils.CollUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;

@Slf4j
@Component
@RequiredArgsConstructor
public class DynamicRouteLoader {

    private final RouteDefinitionWriter writer;
    private final NacosConfigManager nacosConfigManager;
    private final ApplicationEventPublisher eventPublisher; // 新增事件发布

    private final String dataId = "gateway-routes.json";
    private final String group = "DEFAULT_GROUP";
    private final Set<String> routeIds = new HashSet<>();

    @PostConstruct
    public void initRouteConfigListener() throws NacosException {
        // 1.首次拉取配置
        String initialConfig = nacosConfigManager.getConfigService()
                .getConfig(dataId, group, 5000);
        updateRoutes(initialConfig);

        // 2.注册监听器
        nacosConfigManager.getConfigService()
                .addListener(dataId, group, new Listener() {
                    @Override
                    public Executor getExecutor() {
                        return null; // 使用默认线程池
                    }

                    @Override
                    public void receiveConfigInfo(String configInfo) {
                        updateRoutes(configInfo);
                    }
                });
    }

    private void updateRoutes(String configInfo) {
        log.info("监听到路由配置变更: {}", configInfo);
        try {
            // 1.反序列化
            List<RouteDefinition> definitions = JSONUtil.toList(configInfo, RouteDefinition.class);

            // 2.清空旧路由
            routeIds.forEach(id -> writer.delete(Mono.just(id)).subscribe());
            routeIds.clear();

            // 3.添加新路由
            if (!CollUtils.isEmpty(definitions)) {
                definitions.forEach(definition -> {
                    writer.save(Mono.just(definition)).subscribe();
                    routeIds.add(definition.getId());
                });
                // 关键！触发路由刷新
                eventPublisher.publishEvent(new RefreshRoutesEvent(this));
                log.info("路由更新完成，共加载 {} 条路由", definitions.size());
            }
        } catch (Exception e) {
            log.error("路由配置解析失败", e);
        }
    }
}